package com.example.util;

import com.alibaba.fastjson.JSONObject;
import io.jsonwebtoken.*;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class JwtTokenUtil {

    private static Logger log = LoggerFactory.getLogger(JwtTokenUtil.class);
    public static final String TOKEN_HEADER = "Authorization";
    public static final String TOKEN_PREFIX = "Bearer ";
    public  static final String SUBJECT = "hnjwt";
    //过期时间60秒
    private static final long EXPIRITION = 1000 * 60;

    //密钥 -- 根据实际项目，这里可以做成配置
    public static final String KEY =
            "022bdc63c3c5a45879ee6581508b9d03adfec4a4658c0ab3d722e50c91a351c42c231cf43bb8f86998202bd301ec52239a74fc0c9a9aeccce604743367c9646b";        //appsecret_key

    private static final String ROLE_CLAIMS = "role";

    /**
     * 由字符串生成加密key
     *
     * @return
     */
    public static SecretKey generalKey() {
        byte[] encodedKey = Base64.decodeBase64(KEY);
        SecretKeySpec key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
        return key;
    }


    /**
     * user生成token
     *
     * @param username
     * @param role
     * @return
     */
    public static String createToken(String userId, String username, String role) {

        Map<String, Object> map = new HashMap<>();
        map.put(ROLE_CLAIMS, role);
        Date date = new Date(System.currentTimeMillis() + EXPIRITION);
        String token = Jwts
                .builder()
                .setSubject(username)
                .setClaims(map)
                .claim("userId", userId)
                .setIssuedAt(new Date())                                             //签发时间
                .setExpiration(date)   //过期时间
                .signWith(SignatureAlgorithm.HS256, generalKey()).compact();      // 设置签名使用的签名算法和签名使用的秘钥
        return token;
    }

    /**
     * unionid生成token
     *
     * @param unionid
     * @return
     */
    public static String createToken(String unionid) {

        Map<String, Object> map = new HashMap<>();
        map.put("unionid", unionid);

        String token = Jwts
                .builder()
                .setClaims(map)
                .setSubject(SUBJECT)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRITION))
                .signWith(SignatureAlgorithm.HS256, generalKey()).compact();
        return token;
    }

    /**
     * APPid和openid
     *
     * @param appId,openId
     * @return
     */
    public static String createToken(String appId, String openId) {

        Map<String, Object> map = new HashMap<>();
        map.put("appId", appId);
        map.put("openId",openId);

        String token = Jwts
                .builder()
                .setClaims(map)
                .setSubject(SUBJECT)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRITION))
                .signWith(SignatureAlgorithm.HS256, generalKey())
                .compact();
        return token;
    }


    /**
     *
     *默认
     * @param
     * @return
     */
    public static String createToken() {
        String token = Jwts
                .builder()
                .setSubject(SUBJECT)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRITION))
                .signWith(SignatureAlgorithm.HS256, generalKey()).compact();
        return token;
    }

    /**
     * 解密jwt
     *
     * @param authHeader
     * @return
     * @throws Exception
     */
    public static JSONObject checkJWT(String authHeader) throws Exception {
        JSONObject jsonObject =new JSONObject();

        // 获取token
        final String token = authHeader.substring(7);
        try {
            Jws<Claims> claimsJws = Jwts.parser().setSigningKey(generalKey()).parseClaimsJws(token);
            Claims claims = claimsJws.getBody();
            jsonObject.put("code",200);
            jsonObject.put("claims",claims);
            return jsonObject;
        } catch (ExpiredJwtException eje) {
            log.error("===== Token过期 =====", eje);
            jsonObject.put("code","70001");
            jsonObject.put("message","===== Token过期 =====，请重新登录");
            throw  new RuntimeException(jsonObject.toJSONString());

        } catch (Exception e) {
            log.error("===== token解析异常 =====", e);
            jsonObject.put("code","70002");
            jsonObject.put("message","===== token解析异常 =====");
            throw new RuntimeException(jsonObject.toJSONString());

        }
    }



    /**
     * 获取用户名
     *
     * @param token
     * @return
     */
    public static String getUsername(String token) {
        Claims claims = Jwts.parser().setSigningKey(generalKey()).parseClaimsJws(token).getBody();
        return claims.get("username").toString();
    }

    /**
     * 获取用户角色
     *
     * @param token
     * @return
     */
    public static String getUserRole(String token) {
        Claims claims = Jwts.parser().setSigningKey(generalKey()).parseClaimsJws(token).getBody();
        claims.get("rol").toString();
        return claims.get("rol").toString();
    }

    /**
     * 是否过期
     *
     * @param token
     * @return
     */
    public static boolean isExpiration(String token) {
        Claims claims = Jwts.parser().setSigningKey(generalKey()).parseClaimsJws(token).getBody();
        boolean bool_token = claims.getExpiration().before(new Date());
        return bool_token;
    }


}
